1.12 Preprocessor Directives in C Programming

Module 1.12 • Preprocessing Mechanics, Macros Expansion & Conditional Compilation

1.12.1 Introduction

Before a C program is compiled, it passes through a special stage called preprocessing. During this stage, instructions known as Preprocessor Directives are processed.

These directives:

Compilation Flow

Source Code
     ↓
Preprocessor
     ↓
Compiler
     ↓
Object Code
     ↓
Executable Program

1.12.2 Features of Preprocessor Directives

Characteristics

Example:

#include <stdio.h>
 
#define LIMIT 100

1.12.3 Common Preprocessor Directives

Directive Purpose
#includeInclude files
#defineCreate constants/macros
#undefRemove macro definition
#ifConditional compilation
#ifdefCheck if macro exists
#ifndefCheck if macro does not exist
#elseAlternative condition
#elifAdditional condition
#endifEnd condition block
#pragmaCompiler-specific instruction
#errorGenerate custom compile error
#lineChange line information

1.12.4 The #include Directive

Used to include external files.

Standard Library Header

#include <stdio.h>

Compiler searches predefined system folders.

User Defined Header

#include "student.h"

Compiler searches current folder first.

1.12.5 Why Use Header Files?

Header files contain:

Example:

#include "math_utils.h"

Benefits:

1.12.6 The #define Directive

Used to create symbolic constants.

Example

#define TAX_RATE 18

Usage:

total = amount + TAX_RATE;

The preprocessor replaces TAX_RATE with 18.

1.12.7 Symbolic Constants Example

#include <stdio.h>
 
#define MAX_STUDENTS 60
 
int main()
{
    printf("Maximum Students = %d", MAX_STUDENTS);
 
    return 0;
}

Output:

Maximum Students = 60

1.12.8 Macro Expansion

Macros can replace text.

#define MESSAGE "Welcome to Coding Hub"

Example:

printf(MESSAGE);

Expands to:

printf("Welcome to Coding Hub");

1.12.9 Macros with Arguments

Macros can accept parameters.

Syntax

#define MACRO(parameter) expansion

Example:

#define DOUBLE(x) ((x)+(x))

1.12.10 Example Program

#include <stdio.h>
 
#define DOUBLE(x) ((x)+(x))
 
int main()
{
    int value = 14;
 
    printf("%d", DOUBLE(value));
 
    return 0;
}

Output:

28

1.12.11 Area Calculation Macro

#define RECT_AREA(l,w) ((l)*(w))

Program:

#include <stdio.h>
 
#define RECT_AREA(l,w) ((l)*(w))
 
int main()
{
    printf("%d", RECT_AREA(8,5));
 
    return 0;
}

Output:

40

1.12.12 Maximum Macro

#define MAX(a,b) ((a)>(b)?(a):(b))

Example:

MAX(35,21)

Result:

35

1.12.13 Minimum Macro

#define MIN(a,b) ((a)<(b)?(a):(b))

Example:

MIN(42,15)

Result:

15

1.12.14 Importance of Parentheses

Incorrect:

#define MULTIPLY(x,y) x*y

Using:

MULTIPLY(3+2,4+1)

Expands to:

3+2*4+1

Result:

12

Expected:

25

1.12.15 Correct Macro Design

Correct version:

#define MULTIPLY(x,y) ((x)*(y))

Now:

MULTIPLY(3+2,4+1)

Expands to:

((3+2)*(4+1))

Result:

25

1.12.16 Nested Macros

One macro can use another.

#define RATE 12
#define DOUBLE_RATE (RATE*2)

Example:

salary = DOUBLE_RATE;

Expands to:

salary = (12*2);

1.12.17 Example of Nested Macros

#include <stdio.h>
 
#define LOWER(c) ((c)>='a' && (c)<='z')
#define ALPHA(c) (LOWER(c) || ((c)>='A' && (c)<='Z'))
 
int main()
{
    char ch='G';
 
    if(ALPHA(ch))
        printf("Alphabet");
 
    return 0;
}

Output:

Alphabet

1.12.18 Macro vs Function

Feature Macro Function
SpeedFasterSlightly slower
MemoryMoreLess
Type CheckingNoYes
DebuggingDifficultEasier
SafetyLowerHigher

1.12.19 When to Use Macros?

Good for:

Example:

#define PI 3.14159

Avoid macros for:

1.12.20 The #undef Directive

Removes a macro definition.

Example

#define LIMIT 500
 
#undef LIMIT

After removal, LIMIT is no longer recognized.

1.12.21 Example of #undef

#include <stdio.h>
 
#define VERSION 2
 
int main()
{
    printf("%d\n",VERSION);
 
    #undef VERSION
 
    return 0;
}

Output:

2

1.12.22 Conditional Compilation

Sometimes code should compile only under certain conditions. Used directives:

1.12.23 The #if Directive

Example

#define LEVEL 5
 
#if LEVEL > 3
printf("Advanced User");
#endif

Output:

Advanced User

1.12.24 #if Example Program

#include <stdio.h>
 
#define MARKS 85
 
int main()
{
#if MARKS >= 50
    printf("Pass");
#endif
 
    return 0;
}

Output:

Pass

1.12.25 The #else Directive

#define TEMP 20
 
#if TEMP > 30
    printf("Hot");
#else
    printf("Pleasant");
#endif

Output:

Pleasant

1.12.26 The #elif Directive

#define GRADE 2
 
#if GRADE==1
    printf("Excellent");
#elif GRADE==2
    printf("Very Good");
#elif GRADE==3
    printf("Good");
#else
    printf("Average");
#endif

Output:

Very Good

1.12.27 The #ifdef Directive

Checks whether a macro exists.

#define TEST_MODE

Example:

#ifdef TEST_MODE
    printf("Testing Enabled");
#endif

Output:

Testing Enabled

1.12.28 The #ifndef Directive

Checks whether macro does not exist.

#ifndef BUFFER_SIZE
#define BUFFER_SIZE 256
#endif

Used frequently in header files.

1.12.29 Header Guard Example

#ifndef STUDENT_H
#define STUDENT_H
 
struct Student
{
    int roll;
};
 
#endif

Prevents duplicate inclusion.

1.12.30 The defined Operator

Used with #if.

Example:

#if defined(DEBUG)
    printf("Debug Build");
#endif

1.12.31 Multiple Macro Check

#if defined(USER) && defined(PASSWORD)
    printf("Login Enabled");
#endif

1.12.32 Debugging Using Macros

#define DEBUG

Program:

#ifdef DEBUG
printf("Function Started\n");
#endif

Output:

Function Started

1.12.33 Disabling Debug Messages

Simply remove:

#define DEBUG

Now debug messages disappear automatically.

1.12.34 The #error Directive

Creates compile-time error messages.

Example:

#ifndef VERSION
#error VERSION not defined
#endif

Compiler Output:

VERSION not defined

1.12.35 The #line Directive

Changes line number information.

Example:

#line 200

Compiler treats next line as line 200.

1.12.36 The #pragma Directive

Provides compiler-specific instructions.

Example:

#pragma warning(disable:4996)

Used mainly for:

1.12.37 Predefined Macros

C automatically provides predefined macros.

Macro Description
__DATE__Compilation date
__TIME__Compilation time
__FILE__Current file name
__LINE__Current line number
__STDC__ANSI C support

1.12.38 Displaying Compilation Information

#include <stdio.h>
 
int main()
{
    printf("%s\n",__DATE__);
    printf("%s\n",__TIME__);
 
    return 0;
}

Output Example:

Jun 15 2026
14:32:10

1.12.39 Using FILE

printf("%s", __FILE__);

Possible Output:

main.c

1.12.40 Using LINE

printf("%d", __LINE__);

Output:

25

(Depends on actual line number.)

1.12.41 Stringizing Operator (#)

Converts macro arguments into strings.

Example

#define DISPLAY(x) printf(#x)

Usage:

DISPLAY(Programming)

Output:

Programming

1.12.42 Stringizing Example

#include <stdio.h>
 
#define SHOW(v) printf(#v " = %d",v)
 
int main()
{
    int marks = 92;
 
    SHOW(marks);
 
    return 0;
}

Output:

marks = 92

1.12.43 Token Pasting Operator (##)

Combines two tokens.

Example:

#define JOIN(a,b) a##b

Usage:

JOIN(score,1)

Produces:

score1

1.12.44 Token Pasting Example

#include <stdio.h>
 
#define JOIN(a,b) a##b
 
int main()
{
    int roll1 = 110;
 
    printf("%d", JOIN(roll,1));
 
    return 0;
}

Output:

110

1.12.45 Advantages of Preprocessor Directives

1.12.46 Applications

Summary

Verify Comprehension: Technical Knowledge Assessment

Click your choice for each question to view feedback immediately. Complete all questions to evaluate your metric score.